home *** CD-ROM | disk | FTP | other *** search
/ Ray Dream Studio 5 / Ray Dream.iso / pc / DreamSDK / Windows / SAMPLES / ATMOS / FOG / COMFOG.CPP next >
Encoding:
C/C++ Source or Header  |  1997-07-11  |  8.0 KB  |  235 lines

  1. // Copyright (c)1995 Ray Dream, Inc. All Rights Reserved.
  2. /* $Id: COMFog.cpp 1.4 1997/04/10 00:53:01 damien Exp $ */
  3.  
  4. ////////////////////////////////////////////////////////////////////////
  5. //   AtmosphericShader Example : Atmos                                //
  6. //--------------------------------------------------------------------//
  7. //   Implementation of the Atmos Interface                            //
  8. //////////////////////////////////////////////////////////////////////// 
  9.  
  10. #include "math.h"
  11.  
  12. #ifndef __COMFOG__
  13. #include "COMFOG.h"
  14. #endif
  15.  
  16. #ifndef __FOGDLL__
  17. #include "FOGDLL.h"
  18. #endif
  19.  
  20. // Failure Handling
  21. #ifndef __3DCOFAIL__
  22. #include "3DCoFail.h"
  23. #endif
  24.  
  25. #undef INTERFACE
  26. #define INTERFACE Atmos
  27. // Constructor / Destructor of the C++ Object :
  28. Atmos::Atmos() {
  29.   fCRef=0; // Reference Counter
  30.   // Data initialisation :
  31.   fData.fColor.Mode=0;            // White
  32.   fData.fColor.R=1.0;
  33.   fData.fColor.G=1.0;
  34.   fData.fColor.B=1.0;
  35.   fData.fZmin=0.0;      // from 0 to 20"
  36.   fData.fZmax=5.0;
  37.   fData.fVisibility=10.0; 
  38.   }
  39.   
  40. Atmos::~Atmos() {
  41.   global_count_Obj--; 
  42.   }
  43.   
  44. // IUnknown Interface :
  45. HRESULT Atmos::QueryInterface(THIS_ REFIID riid,LPVOID* ppvObj) {
  46.   *ppvObj=NULL;
  47.   
  48.   // The Atmos knows the interfaces of the parent Objects
  49.   if (IsEqualIID(riid, IID_IUnknown))
  50.     *ppvObj=(LPVOID)this;
  51.   else if (IsEqualIID(riid, IID_I3DExAtmosphericShader))
  52.     *ppvObj=(LPVOID)this;
  53.   else if (IsEqualIID(riid, IID_I3DExDataExchanger))
  54.     *ppvObj=(LPVOID)this;
  55.   else if (IsEqualIID(riid, IID_I3DExtension))
  56.     *ppvObj=(LPVOID)this;
  57.     
  58.   // we must add reference if we return an interface
  59.   if (*ppvObj!=NULL) {
  60.     ((LPUNKNOWN)*ppvObj)->AddRef();
  61.     return NOERROR;
  62.     }
  63.   else {
  64.     return ResultFromScode(E_NOINTERFACE);
  65.     }
  66.   }
  67.  
  68. ULONG Atmos::AddRef(THIS) {
  69.   return fCRef++;
  70.   }
  71.   
  72. ULONG Atmos::Release(THIS) {
  73.   ULONG UnreleaseObject=fCRef--;
  74.   
  75.   if (fCRef==0)
  76.      delete this; // No reference left, so destroy the object
  77.   
  78.   return UnreleaseObject;
  79.   // local variable used, because fCRef can be destroyed before.
  80.   }
  81.   
  82. // I3DExtension methods :
  83. I3DExtension* Atmos::Clone(THIS) {
  84.   Atmos* theClone = new Atmos;
  85.   if (theClone) {
  86.     theClone->AddRef();
  87.     theClone->fData=fData; // copy the AtmosData
  88.     }                               
  89.   return theClone;
  90.   }   
  91.  
  92. HRESULT Atmos::ShellUtilitiesInit(THIS_ IShUtilities* shellUtilities) {
  93.   InitCoFailure(shellUtilities);
  94.   return NOERROR;
  95.   }
  96.  
  97. // I3DExDataExchanger methods :
  98. ExtensionDataMap* Atmos::GetExtensionDataMap(THIS) {
  99.   return NULL;
  100.   }
  101.  
  102. void* Atmos::GetExtensionDataBuffer(THIS) {
  103.   return &fData; // used by the shell to set the new parameters
  104.   }
  105.   
  106. HRESULT Atmos::ExtensionDataChanged(THIS) {
  107.   return NOERROR;
  108.   }
  109.  
  110. HRESULT Atmos::HandleEvent(THIS_ ULONG SourceID) {
  111.   return ResultFromScode(E_NOTIMPL);
  112.   }
  113.  
  114. short Atmos::GetResID(THIS) {
  115.   return 134; // this is the view ID in the resource file.
  116.   }
  117.   
  118. // I3DExAtmosphericShader methods :
  119. HRESULT Atmos::SegmentFilter(THIS_ VECTOR3D* beg, VECTOR3D* end, COLOR3D* filterOut) {
  120.   NUM3D    distanceInTheFog;
  121.   VECTOR3D beamVector;
  122.   VECTOR3D beaminfogbeg,beaminfogend;
  123.   NUM3D    filtercoef,colorcoef;
  124.   if (((*beg)[2]>fData.fZmax)&&((*end)[2]>fData.fZmax)) { // the light beam is above the fog
  125.     // Don't do anything
  126.     }             
  127.   else if (((*beg)[2]<fData.fZmin)&&((*end)[2]<fData.fZmin)) { // the light beam is under the fog
  128.     // Don't do anything
  129.     }
  130.   else { // The Light beam crosses the fog
  131.     if ((*beg)[2]>fData.fZmax) {
  132.       beaminfogbeg[2]=fData.fZmax;
  133.       beaminfogbeg[0]=(*beg)[0]+((*end)[0]-(*beg)[0])/((*end)[2]-(*beg)[2])*(fData.fZmax-(*beg)[2]);
  134.       beaminfogbeg[1]=(*beg)[1]+((*end)[1]-(*beg)[1])/((*end)[2]-(*beg)[2])*(fData.fZmax-(*beg)[2]);
  135.       }
  136.     else if ((*beg)[2]<fData.fZmin) {
  137.       beaminfogbeg[2]=fData.fZmin;
  138.       beaminfogbeg[0]=(*beg)[0]+((*end)[0]-(*beg)[0])/((*end)[2]-(*beg)[2])*(fData.fZmin-(*beg)[2]);
  139.       beaminfogbeg[1]=(*beg)[1]+((*end)[1]-(*beg)[1])/((*end)[2]-(*beg)[2])*(fData.fZmin-(*beg)[2]);
  140.       }
  141.     else {
  142.       beaminfogbeg[0]=(*beg)[0];
  143.       beaminfogbeg[1]=(*beg)[1];
  144.       beaminfogbeg[2]=(*beg)[2]; // the begining point of the light beam is in the fog
  145.       }
  146.     if ((*end)[2]>fData.fZmax) {
  147.       beaminfogend[2]=fData.fZmax;
  148.       beaminfogbeg[0]=(*beg)[0]+((*end)[0]-(*beg)[0])/((*end)[2]-(*beg)[2])*(fData.fZmax-(*beg)[2]);
  149.       beaminfogbeg[1]=(*beg)[1]+((*end)[1]-(*beg)[1])/((*end)[2]-(*beg)[2])*(fData.fZmax-(*beg)[2]);
  150.       }
  151.     else if ((*end)[2]<fData.fZmin) {
  152.       beaminfogend[2]=fData.fZmin;
  153.       beaminfogend[0]=(*beg)[0]+((*end)[0]-(*beg)[0])/((*end)[2]-(*beg)[2])*(fData.fZmin-(*beg)[2]);
  154.       beaminfogend[1]=(*beg)[1]+((*end)[1]-(*beg)[1])/((*end)[2]-(*beg)[2])*(fData.fZmin-(*beg)[2]);
  155.       }                     
  156.     else {
  157.       beaminfogend[0]=(*end)[0];
  158.       beaminfogend[1]=(*end)[1];
  159.       beaminfogend[2]=(*end)[2]; // the ending point of the light beam is in the fog
  160.       }
  161.     beamVector[0]=beaminfogend[0]-beaminfogbeg[0];
  162.     beamVector[1]=beaminfogend[1]-beaminfogbeg[1];
  163.     beamVector[2]=beaminfogend[2]-beaminfogbeg[2];
  164.     distanceInTheFog=sqrt(SQR(beamVector[0]) + SQR(beamVector[1]) + SQR(beamVector[2]));
  165.     filtercoef=1.0-distanceInTheFog/fData.fVisibility;
  166.     if (filtercoef<0.0) {
  167.       filtercoef=0.0;
  168.       }
  169.     colorcoef=1.0-filtercoef;
  170.     filterOut->R=filterOut->R*filtercoef+fData.fColor.R*colorcoef;
  171.     filterOut->G=filterOut->G*filtercoef+fData.fColor.G*colorcoef;
  172.     filterOut->B=filterOut->B*filtercoef+fData.fColor.B*colorcoef;
  173.     }
  174.   return NOERROR;
  175.   }
  176.   
  177.  
  178. HRESULT Atmos::DirectionFilter(THIS_ VECTOR3D* origin, VECTOR3D* direction, COLOR3D* filterOut) {
  179.   NUM3D    distanceInTheFog;
  180.   VECTOR3D beamVector;
  181.   VECTOR3D beaminfogbeg,beaminfogend;
  182.   NUM3D    filtercoef,colorcoef;
  183.   
  184.   if (((*origin)[2]>fData.fZmax)&&((*direction)[2]>=0.0)) {
  185.     // Don't do anything
  186.     }
  187.   else if (((*origin)[2]<fData.fZmin)&&((*direction)[2]<=0.0)) {
  188.     // Don't do anything
  189.     }
  190.   else {
  191.     if (((*origin)[2]>fData.fZmax)||((*origin)[2]<fData.fZmin)) {
  192.       beaminfogbeg[2]=fData.fZmax;
  193.       beaminfogbeg[0]=(*origin)[0]+(*direction)[0]*(fData.fZmax-(*origin)[2])/(*direction)[2];
  194.       beaminfogbeg[1]=(*origin)[1]+(*direction)[1]*(fData.fZmax-(*origin)[2])/(*direction)[2];
  195.       beaminfogend[2]=fData.fZmin;
  196.       beaminfogend[0]=(*origin)[0]+(*direction)[0]*(fData.fZmin-(*origin)[2])/(*direction)[2];
  197.       beaminfogend[1]=(*origin)[1]+(*direction)[1]*(fData.fZmin-(*origin)[2])/(*direction)[2];
  198.       }
  199.     else if ((*direction)[2]>0.0) {
  200.       beaminfogbeg[0]=(*origin)[0];
  201.       beaminfogbeg[1]=(*origin)[1];
  202.       beaminfogbeg[2]=(*origin)[2];
  203.       beaminfogend[2]=fData.fZmax;
  204.       beaminfogend[0]=(*origin)[0]+(*direction)[0]*(fData.fZmax-(*origin)[2])/(*direction)[2];
  205.       beaminfogend[1]=(*origin)[1]+(*direction)[1]*(fData.fZmax-(*origin)[2])/(*direction)[2];
  206.       }
  207.     else if ((*direction)[2]<0.0) {
  208.       beaminfogbeg[0]=(*origin)[0];
  209.       beaminfogbeg[1]=(*origin)[1];
  210.       beaminfogbeg[2]=(*origin)[2];
  211.       beaminfogend[2]=fData.fZmin;
  212.       beaminfogend[0]=(*origin)[0]+(*direction)[0]*(fData.fZmin-(*origin)[2])/(*direction)[2];
  213.       beaminfogend[1]=(*origin)[1]+(*direction)[1]*(fData.fZmin-(*origin)[2])/(*direction)[2];
  214.       }
  215.     else { // (*direction)[2]=0.0
  216.       *filterOut=fData.fColor;
  217.       return NOERROR; 
  218.       }
  219.     beamVector[0]=beaminfogend[0]-beaminfogbeg[0];
  220.     beamVector[1]=beaminfogend[1]-beaminfogbeg[1];
  221.     beamVector[2]=beaminfogend[2]-beaminfogbeg[2];
  222.     distanceInTheFog=sqrt(SQR(beamVector[0]) + SQR(beamVector[1]) + SQR(beamVector[2]));
  223.     filtercoef=1.0-distanceInTheFog/fData.fVisibility;
  224.     if (filtercoef<0.0) {
  225.       filtercoef=0.0;
  226.       }
  227.     colorcoef=1.0-filtercoef;
  228.     filterOut->R=filterOut->R*filtercoef+fData.fColor.R*colorcoef;
  229.     filterOut->G=filterOut->G*filtercoef+fData.fColor.G*colorcoef;
  230.     filterOut->B=filterOut->B*filtercoef+fData.fColor.B*colorcoef;
  231.     }
  232.   return NOERROR;
  233.   }
  234.   
  235.